package com.hk.blog.config;

import com.hk.commons.JsonResult;
import com.hk.commons.util.StringUtils;
import com.hk.core.authentication.api.UserPrincipal;
import com.hk.core.autoconfigure.authentication.AuthenticationProperties;
import com.hk.core.web.Webs;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.CorsConfigurer;
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Configuration
public class BlogWebSecurityConfigurerAdapter {

    private final AuthenticationProperties authenticationProperties;

    public BlogWebSecurityConfigurerAdapter(AuthenticationProperties authenticationProperties) {
        this.authenticationProperties = authenticationProperties;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.
                cors(CorsConfigurer::disable)
                .csrf(CsrfConfigurer::disable)
//                .httpBasic(httpBasicConfigurer -> httpBasicConfigurer.authenticationEntryPoint())
                .formLogin(formLogin -> {
                    formLogin.loginPage(authenticationProperties.getLogin().getLoginUrl()).permitAll()
                            .usernameParameter(authenticationProperties.getLogin().getUsernameParameter())
                            .passwordParameter(authenticationProperties.getLogin().getPasswordParameter())
                            .loginProcessingUrl(authenticationProperties.getLogin().getLoginProcessingUrl())
                            .successHandler((request, response, authentication) -> {
                                UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
                                Webs.writeJson(response, HttpServletResponse.SC_OK,
                                        JsonResult.success(Map.of(
                                                "account", principal.getAccount(),
                                                "userName", StringUtils.defaultIfEmpty(principal.getRealName(), principal.getAccount()),
                                                "iconPath", StringUtils.defaultIfEmpty(principal.getIconPath(), StringUtils.EMPTY))));
                            })
                            .failureHandler((request, response, exception) ->
                                    Webs.writeJson(response, HttpServletResponse.SC_OK, JsonResult.failure(exception.getMessage())));
                })
                .sessionManagement(sessionConfigure -> sessionConfigure.enableSessionUrlRewriting(false)
                        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                        .maximumSessions(Integer.MAX_VALUE)
                        .expiredSessionStrategy(event -> Webs.writeJson(event.getResponse(), HttpServletResponse.SC_OK, JsonResult.unauthorized("会话已过期"))))
                .logout(logoutConfigure -> logoutConfigure.logoutSuccessHandler((request, response, authentication) ->
                        Webs.writeJson(response, HttpServletResponse.SC_OK, JsonResult.success())))
                .exceptionHandling(exceptionHandler -> exceptionHandler.authenticationEntryPoint((request, response, authException) ->
                        Webs.writeJson(response, HttpServletResponse.SC_OK, JsonResult.unauthorized(authException.getMessage()))))
                .authorizeHttpRequests(authorizeHttp -> authorizeHttp
                        .requestMatchers("/article/get").permitAll()
                        .anyRequest().authenticated())
                .build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        Set<String> patterns = StaticResourceLocation.FAVICON.getPatterns().collect(Collectors.toSet());
        patterns.add("/home/**");
        patterns.add("/article/batch/get");
        patterns.add("/captcha/**");
        patterns.add("/images/**");
        return web -> web.ignoring().requestMatchers(patterns.toArray(String[]::new));
    }
}
